home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Visual Cafe 3
/
Visual Cafe 3.ISO
/
Vcafe
/
Main.bin
/
GZIPInputStream.java
< prev
next >
Wrap
Text File
|
1998-09-22
|
6KB
|
219 lines
/*
* @(#)GZIPInputStream.java 1.15 97/01/20
*
* Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*
* SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
* SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
* SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
* THIS SOFTWARE OR ITS DERIVATIVES.
*
* CopyrightVersion 1.1_beta
*
*/
package java.util.zip;
import java.io.SequenceInputStream;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.EOFException;
/**
* This class implements a stream filter for reading compressed data in
* the GZIP format.
*
* @see InflaterInputStream
* @version 1.15, 01/20/97
* @author David Connelly
*
*/
public
class GZIPInputStream extends InflaterInputStream {
/**
* CRC-32 for uncompressed data.
*/
protected CRC32 crc = new CRC32();
/**
* Indicates end of input stream.
*/
protected boolean eos;
/**
* Creates a new input stream with the specified buffer size.
* @param in the input stream
* @param size the input buffer size
* @exception IOException if an I/O error has occurred
*/
public GZIPInputStream(InputStream in, int size) throws IOException {
super(in, new Inflater(true), size);
readHeader();
crc.reset();
}
/**
* Creates a new input stream with a default buffer size.
* @param in the input stream
* @exception IOException if an I/O error has occurred
*/
public GZIPInputStream(InputStream in) throws IOException {
this(in, 512);
}
/**
* Reads uncompressed data into an array of bytes. Blocks until enough
* input is available for decompression.
* @param buf the buffer into which the data is read
* @param off the start offset of the data
* @param len the maximum number of bytes read
* @return the actual number of bytes read, or -1 if the end of the
* compressed input stream is reached
* @exception IOException if an I/O error has occurred or the compressed
* input data is corrupt
*/
public int read(byte[] buf, int off, int len) throws IOException {
if (eos) {
return -1;
}
len = super.read(buf, off, len);
if (len == -1) {
readTrailer();
eos = true;
} else {
crc.update(buf, off, len);
}
return len;
}
/**
* Closes the input stream.
* @exception IOException if an I/O error has occurred
*/
public void close() throws IOException {
inf.end();
in.close();
eos = true;
}
/**
* GZIP header magic number.
*/
public final static int GZIP_MAGIC = 0x8b1f;
/*
* File header flags.
*/
private final static int FTEXT = 1; // Extra text
private final static int FHCRC = 2; // Header CRC
private final static int FEXTRA = 4; // Extra field
private final static int FNAME = 8; // File name
private final static int FCOMMENT = 16; // File comment
/*
* Reads GZIP member header.
*/
private void readHeader() throws IOException {
CheckedInputStream in = new CheckedInputStream(this.in, crc);
crc.reset();
// Check header magic
if (readUShort(in) != GZIP_MAGIC) {
throw new IOException("Not in GZIP format");
}
// Check compression method
if (readUByte(in) != 8) {
throw new IOException("Unsupported compression method");
}
// Read flags
int flg = readUByte(in);
// Skip MTIME, XFL, and OS fields
skipBytes(in, 6);
// Skip optional extra field
if ((flg & FEXTRA) == FEXTRA) {
skipBytes(in, readUShort(in));
}
// Skip optional file name
if ((flg & FNAME) == FNAME) {
while (readUByte(in) != 0) ;
}
// Skip optional file comment
if ((flg & FCOMMENT) == FCOMMENT) {
while (readUByte(in) != 0) ;
}
// Check optional header CRC
if ((flg & FHCRC) == FHCRC) {
int v = (int)crc.getValue() & 0xffff;
if (readUShort(in) != v) {
throw new IOException("Corrupt GZIP header");
}
}
}
/*
* Reads GZIP member trailer.
*/
private void readTrailer() throws IOException {
InputStream in = this.in;
int n = inf.getRemaining();
if (n > 0) {
in = new SequenceInputStream(
new ByteArrayInputStream(buf, len - n, n), in);
}
long v = crc.getValue();
if (readUInt(in) != v || readUInt(in) != inf.getTotalOut()) {
throw new IOException("Corrupt GZIP trailer");
}
}
/*
* Reads unsigned integer in Intel byte order.
*/
private long readUInt(InputStream in) throws IOException {
long s = readUShort(in);
return ((long)readUShort(in) << 16) | s;
}
/*
* Reads unsigned short in Intel byte order.
*/
private int readUShort(InputStream in) throws IOException {
int b = readUByte(in);
return ((int)readUByte(in) << 8) | b;
}
/*
* Reads unsigned byte.
*/
private int readUByte(InputStream in) throws IOException {
int b = in.read();
if (b == -1) {
throw new EOFException();
}
return b;
}
/*
* Skips bytes of input data blocking until all bytes are skipped.
* Does not assume that the input stream is capable of seeking.
*/
private void skipBytes(InputStream in, int n) throws IOException {
byte[] buf = new byte[128];
while (n > 0) {
int len = in.read(buf, 0, n < buf.length ? n : buf.length);
if (len == -1) {
throw new EOFException();
}
n -= len;
}
}
}